package main

import (
	"context"
	"net/http"
	"strconv"
	"strings"

	"github.com/gin-gonic/gin"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
)

//API the APIs
type API struct {
	db *mongo.Database
}

//Page the web page content
type Page struct {
	ID      primitive.ObjectID `bson:"_id"`
	title   string
	date    string
	Content []Content
}

//Content content of page
type Content struct {
	Title   string
	Type    string
	Content string
	Style   string
}

//CreatePage create the page
func (api *API) CreatePage(c *gin.Context) {
	var json Page
	if err := c.ShouldBindJSON(&json); err != nil {
		c.JSON(http.StatusOK, gin.H{"error": err.Error()})
		return
	}
	result, err := api.db.Collection("Page").InsertOne(context.TODO(), json)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{"error": err.Error()})
		return
	}
	if result.InsertedID == nil {
		c.JSON(http.StatusOK, gin.H{"error": "无法新建页面"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"ID": result.InsertedID})
}

//UpdatePage create the page
func (api *API) UpdatePage(c *gin.Context) {
	ID := c.Param("ID")

	dbID, err := primitive.ObjectIDFromHex(ID)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{"error": err.Error()})
		return
	}
	result, err := api.db.Collection("Page").UpdateOne(context.TODO(), bson.M{"_id": dbID})
	if err != nil {
		c.JSON(http.StatusOK, gin.H{"error": err.Error()})
		return
	}
	if result.ModifiedCount < 1 {
		c.JSON(http.StatusOK, gin.H{"error": "修改失败"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"status": "修改成功"})
}

//DeletePage delete the page
func (api *API) DeletePage(c *gin.Context) {
	ID := c.Param("ID")

	dbID, err := primitive.ObjectIDFromHex(ID)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{"error": err.Error()})
		return
	}
	result, err := api.db.Collection("Page").DeleteOne(context.TODO(), bson.M{"_id": dbID})
	if err != nil {
		c.JSON(http.StatusOK, gin.H{"error": err.Error()})
		return
	}
	if result.DeletedCount < 1 {
		c.JSON(http.StatusOK, gin.H{"error": "删除失败"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"status": "删除成功"})
}

//FindPage delete the page
func (api *API) FindPage(c *gin.Context) {
	start := c.DefaultQuery("current", "1")
	limit := c.DefaultQuery("pageSize", "10")
	sort := c.DefaultQuery("sort", "_id")
	order := c.DefaultQuery("order", "DESC")
	Title := c.DefaultQuery("Title", "")
	Order := 1
	if strings.ToUpper(order) == "DESC" {
		Order = -1
	}
	Start, err := strconv.ParseInt(start, 10, 64)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	Limit, err := strconv.ParseInt(limit, 10, 64)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	Skip := (Start - 1) * Limit
	var got *primitive.D = &bson.D{}
	if Title != "" {
		got, err = MakeFilterBSOND(TCondition{Key: "Title", Type: "string", Opt: "$like", Value: Title})
	}
	total, err := api.db.Collection("Page").CountDocuments(context.TODO(), got, &options.CountOptions{})
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	paging := &TPaging{Skip: &Skip, Limit: &Limit, SortKey: sort, SortVal: Order, Condition: got}
	cur, err := api.db.Collection("Page").Find(context.TODO(), paging, &options.FindOptions{
		Skip:  paging.Skip,
		Sort:  bson.D{bson.E{Key: paging.SortKey, Value: paging.SortVal}},
		Limit: paging.Limit,
	})
	defer cur.Close(context.TODO())
	pages := []Page{}
	err = cur.All(context.Background(), &pages)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	if len(pages) > 1 {
		c.JSON(http.StatusOK, gin.H{
			"data":     pages,
			"success":  true,
			"total":    total,
			"pageSize": Limit,
			"current":  Start,
		})
	} else {
		c.JSON(http.StatusOK, gin.H{
			"data":     []Page{},
			"success":  true,
			"total":    total,
			"pageSize": Limit,
			"current":  Start,
		})
	}
}
